package com.north.light.libdownload.function;

import android.text.TextUtils;

import com.north.light.libdownload.DownloadListener;

import java.io.File;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.concurrent.atomic.AtomicInteger;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;


/**
 * 文件下载管理器
 *
 * @author liuyazhuang
 */
public class LibDownloadManager {
    //下载线程的数量
    private static final int TREAD_SIZE = 3;

    static {
        handleSSLHandshake();
    }

    public static void handleSSLHandshake() {
        try {
            TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }

                @Override
                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                }

                @Override
                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                }
            }};
            SSLContext sc = SSLContext.getInstance("TLS");
            //trustAllCerts信任所有的证书
            sc.init(null, trustAllCerts, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 下载文件的方法
     * <p>
     * change by lzt 20211011 修改传入链接如果是Https则替换为http
     *
     * @param urlOrg：下载文件的路径
     * @param listener：自定义的下载文件监听接口
     */
    private void download(boolean replaceHttps, String storagePath, String urlOrg, LibInnerProgressBarListener listener) {
        try {
            String urlPath = (replaceHttps) ? urlOrg.replace("https", "http") : urlOrg;
            URL url = new URL(urlPath);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            conn.setRequestMethod("GET");
            String fileName = this.getFileName(urlPath);
            if (conn.getResponseCode() == 200) {
                int fileSize = conn.getContentLength();
                //创建一个和服务器大小一样的文件
                File file = new File(storagePath, fileName);
                boolean clearCache = (!file.exists());
                //add by lzt 20230103 增加判断文件大小是否一致，若不一致，则不走断点下载逻辑
                if (file.exists()) {
                    long fileLength = file.length();
                    clearCache = (fileLength != fileSize);
                }
                RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
                accessFile.setLength(fileSize);
                //要关闭RandomAccessFile对象
                accessFile.close();
                //设置进度条的最大长度
                listener.getMax(fileSize, file.getPath(), fileName);
                //计算出每条线程下载的数据量
                int block = fileSize % TREAD_SIZE == 0 ? (fileSize / TREAD_SIZE) : (fileSize / TREAD_SIZE + 1);
                //开启线程下载
                LibDownloadExecutorsManager.getInstance().closeCacheExecutors(urlPath);
                for (int i = 0; i < TREAD_SIZE; i++) {
                    LibDownloadExecutorsManager.getInstance().getCacheExecutors(urlPath)
                            .execute(new LibDownloadThread(i, urlPath, file, listener, block, clearCache, fileName));
                }
            } else {
                if (listener != null) {
                    listener.error("download error");
                }
            }
        } catch (Exception e) {
            if (listener != null) {
                listener.error(e.getMessage());
            }
        }
    }

    /**
     * 截取路径中的文件名称
     *
     * @param path:要截取文件名称的路径
     * @return:截取到的文件名称
     */
    private String getFileName(String path) {
        return path.substring(path.lastIndexOf("/") + 1);
    }


    //外部调用方法---------------------------------------------------------------------------------


    /**
     * 开启
     */
    protected void start(boolean replaceHttps, final String storagePath, final String urlPath, final DownloadListener listener) {
        if (TextUtils.isEmpty(storagePath) || TextUtils.isEmpty(urlPath)) {
            if (listener != null) {
                listener.error("download params error");
            }
            return;
        }
        //总进度
        final AtomicInteger total = new AtomicInteger();
        final AtomicInteger current = new AtomicInteger();
        String fileName = this.getFileName(urlPath);
        if (listener != null && !listener.checkNeedToDownload(urlPath, storagePath, fileName)) {
            return;
        }
        download(replaceHttps, storagePath, urlPath, new LibInnerProgressBarListener() {
            @Override
            public void getMax(int length, String localPath, String fileName) {
                total.set(length);
                if (listener != null) {
                    listener.data(urlPath, total.get(), 0, 0, false, localPath, fileName);
                }
            }

            @Override
            public void getDownload(int length, String localPath, String fileName) {
                if (listener != null) {
                    Float tol = total.get() / 1f;
                    Float cur = current.addAndGet(length) / 1f;
                    float percent = cur / tol;
                    if (percent < 0 || percent > 100) {
                        return;
                    }
                    listener.data(urlPath, tol.longValue(), cur.longValue(), percent, (tol.equals(cur)), localPath, fileName);
                }
            }


            @Override
            public void error(String msg) {
                if (listener != null) {
                    listener.error(msg);
                }
            }

            @Override
            public void setProgress(String key, long pro) {
                if (listener != null) {
                    listener.setProgress(key, pro);
                }
            }

            @Override
            public Long getProgress(String key) {
                if (listener != null) {
                    return listener.getProgress(key);
                }
                return 0L;
            }
        });
    }


    /**
     * 关闭
     */
    protected Boolean stop(String path) {
        return LibDownloadExecutorsManager.getInstance().closeCacheExecutors(path);
    }


}
